-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Integrate TIFF access into vitessce-image-viewer and Improve Metadata Caching #31
Conversation
import {BaseTileLayer} from '@deck.gl/layers'; | ||
import {Texture2D} from '@luma.gl/webgl' | ||
import GL from '@luma.gl/constants'; | ||
import { COORDINATE_SYSTEM } from 'deck.gl'; | ||
import { XRLayer } from '../xr-layer'; | ||
import {tileToBoundingBox} from './tiling-utils'; | ||
import {getTileIndices} from './tiling-utils'; | ||
import { loadZarr, loadTiff } from './data-utils'; | ||
|
||
const defaultProps = Object.assign({}, BaseTileLayer.defaultProps, { | ||
id: `microscopy-tile-layer`, | ||
pickable: false, | ||
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN, | ||
maxZoom: 0, | ||
onViewportLoad: false, | ||
renderSubLayers: (props) => { | ||
const { | ||
bbox: { | ||
west, south, east, north, | ||
}, | ||
} = props.tile; | ||
const { sliderValues, data, colorValues } = props; | ||
const xrl = new XRLayer(props, { | ||
id: `XR-Layer-${west}-${south}-${east}-${north}`, | ||
pickable: false, | ||
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN, | ||
rgbData: data, | ||
sliderValues, | ||
colorValues, | ||
bounds: [west, south, east, north], | ||
visible: true, | ||
}); | ||
return xrl; | ||
}, | ||
}); | ||
|
||
export class MicroscopyViewerLayerBase extends BaseTileLayer { | ||
|
||
constructor(props) { | ||
const minZoom = Math.floor(-1 * Math.log2(Math.max(props.imageHeight, props.imageWidth))); | ||
const {sliderValues, colorValues} = props | ||
var orderedSliderValues = [] | ||
var orderedColorValues = [] | ||
Object.keys(sliderValues).sort().forEach(function(key) { | ||
orderedSliderValues.push(sliderValues[key]); | ||
}) | ||
Object.keys(colorValues).sort().forEach(function(key) { | ||
orderedColorValues.push(colorValues[key]); | ||
}) | ||
var diff = 6 - orderedSliderValues.length | ||
for (var i = 0; i < diff; i++) { | ||
orderedSliderValues.push(65535); | ||
} | ||
var diff = 6 - orderedColorValues.length | ||
for (var j = 0; j < diff; j++) { | ||
orderedColorValues.push([0,0,0]); | ||
} | ||
orderedColorValues = orderedColorValues.map(color => color.map(ch => ch / 255)) | ||
const getZarr = ({ x, y, z }) => { | ||
return loadZarr({ | ||
x, y, z: -1 * z, ...props, | ||
}); | ||
} | ||
const getTiff = ({ x, y, z }) => { | ||
return loadTiff({ | ||
x, y, z: -1 * z, ...props, | ||
}); | ||
} | ||
const getTileData = (props.useZarr && getZarr) || | ||
(props.useTiff && getTiff) || | ||
props.getTileData | ||
const overrideValuesProps = Object.assign( | ||
{}, props, { | ||
sliderValues: orderedSliderValues, | ||
colorValues: orderedColorValues, | ||
minZoom, | ||
getTileData, | ||
getTileIndices: (viewport, maxZoom, minZoom) => { | ||
return getTileIndices({ | ||
viewport, maxZoom, minZoom, ...props, | ||
}); | ||
}, | ||
tileToBoundingBox: (x, y, z) => { | ||
return tileToBoundingBox({ | ||
x, y, z, ...props, | ||
}); | ||
}, | ||
} | ||
) | ||
const layerProps = Object.assign({}, defaultProps, overrideValuesProps) | ||
super(layerProps) | ||
} | ||
|
||
} | ||
|
||
MicroscopyViewerLayerBase.layerName = 'MicroscopyViewerLayerBase'; | ||
MicroscopyViewerLayerBase.defaultProps = defaultProps; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copy and pasted into a new file :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could turn on linting in Travis? Whatever rules we have on Vitessce are fine. Whatever the linting would complain about, I'd like to complain about, and it's easier for the computer to do the complaining. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last few comments have all just been linting issues. Please get it turned on, and then I'll give it another look. Thanks!
@@ -44,7 +45,7 @@ This component can be used with an already existing `DeckGL` setup. | |||
|
|||
##### `getTileData` (Function) **POTENIAL FUTURE BREAKING CHANGES WITH NEW FEATURES** | |||
|
|||
`getTileData` given x, y, z indices of the tile, returns the tile data or a Promise that resolves to the tile data. Alternatively, pass in `useZarr` as true to use `zarr` and our funcionality. Soon, there will be a `useGeoTIFF` as well. Look | |||
`getTileData` given x, y, z indices of the tile, returns the tile data or a Promise that resolves to the tile data. Alternatively, pass in `useZarr` as true to use `zarr` and our functionality. Otherwise, you can use `useTiff` to make range requests directly against a pyramid/tiled tiff. Look |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think useZarr
is out, for now? Update docs if so.
channel_0: "https://vitessce-vanderbilt-data.storage.googleapis.com/test-data/vanderbilt-data/tiff-pyramid/vanderbilt_test_0.ome.tiff", | ||
channel_1: "https://vitessce-vanderbilt-data.storage.googleapis.com/test-data/vanderbilt-data/tiff-pyramid/vanderbilt_test_1.ome.tiff", | ||
channel_2: "https://vitessce-vanderbilt-data.storage.googleapis.com/test-data/vanderbilt-data/tiff-pyramid/vanderbilt_test_2.ome.tiff", | ||
channel_3: "https://vitessce-vanderbilt-data.storage.googleapis.com/test-data/vanderbilt-data/tiff-pyramid/vanderbilt_test_3.ome.tiff", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- How do you generate the data that goes on the google service? We need the scripts documented, like in
vitessce-data
. - Make a variable for the repeated string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting to this data task today. Will do for repeated string.
@@ -0,0 +1,46 @@ | |||
import {fromUrl, Pool, getDecoder } from 'geotiff/dist/geotiff.bundle.min.js'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it something about their packaging that forces us to reference it this way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. People seem to have trouble with it
async function loadTile({image, channel, x, y, pool}) { | ||
var tile = await image.getTileOrStrip(x,y, 0, pool) | ||
var dataObj = {} | ||
const bits8 = image.fileDirectory.BitsPerSample[0]===8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here it's clear, but I'd prefer to give booleans is*
names... like is8bit
.
dataObj[channel] = (bits8 && new Uint8Array(tile.data)) || | ||
(bits16 && new Uint16Array(tile.data)) || | ||
(bits32 && new Uint32Array(tile.data)) | ||
return dataObj |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use semicolons... I know they're not really necessary in JS, but consistency is good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will run prettier/eslint later
|
||
export function loadTiff({connections, x, y, z, pool}){ | ||
const configListPromises = Object.keys(connections).map((channel) => { | ||
var image = connections[channel][z] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's not use var.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will run prettier/eslint later
return Promise.all(configListPromises).then((dataList) => { | ||
const orderedList = [] | ||
const dataObj = Object.assign({}, ...dataList) | ||
Object.keys(dataObj).sort().forEach(function(key) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
arrow syntax.
adee215
to
80a60a6
Compare
This looks to finish the work for #15 and #30. Once this is merged (or rather while it's under review), I will begin working on integrating pyramidal tiff into vitessce and vitessce-data. Since the tiff pyramid is a fairly "standard" format in my eyes, I will thus look to make this the default in vitessce and hold off on zarr.